package cn.edu.fzu.delivery.session;

import static cn.edu.fzu.delivery.session.SessionConstant.*;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.edu.fzu.delivery.common.Sn;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class RedisSessionFilter implements Filter {

    private final SessionCache sessionCache;

    @Autowired
    RedisSessionFilter(@Qualifier("sessionCache") SessionCache sessionCache) {
        this.sessionCache = sessionCache;
    }


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // do nothing
    }


    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rsp = (HttpServletResponse) response;

        boolean logout = LOGOUT_URI.equals(req.getRequestURI());

        String domain = req.getServerName();

        // 将 session id 写入 cookie, 如果是退出登录, 则删除 cookie
        Cookie cookie = getOrCreateSessionCookie(req);
        cookie.setDomain(domain);
        cookie.setPath(COOKIE_PATH);
        cookie.setMaxAge(logout ? 0 : SESSION_TIMEOUT);
        rsp.addCookie(cookie);

        String dSessionId = cookie.getValue();
        RedisSession session = sessionCache.get(dSessionId);
        if (logout) {
            sessionCache.invalidate(dSessionId);
        }

        try (RedisSessionRequest requestWrapper = new RedisSessionRequest(req, session)) {
            chain.doFilter(requestWrapper, response);
        }

    }


    @Override
    public void destroy() {
        // do nothing
    }


    // 从 web 端请求中获取 cookie, 如果没有就创建一个
    private static Cookie getOrCreateSessionCookie(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (ArrayUtils.isNotEmpty(cookies)) {
            for (Cookie item : cookies) {
                if (DSESSIONID.equals(item.getName())) {
                    return item;
                }
            }
        }
        return new Cookie(DSESSIONID, Sn.next());
    }

}
